package com.sailing.xjpb.common.web.translate.impl;

import com.sailing.xjpb.common.SailingReflectionUtils;
import com.sailing.xjpb.common.web.translate.TranslateHandler;
import com.sailing.xjpb.common.web.translate.annotation.Translate;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Field;
import java.net.URI;
import java.net.URL;
import java.util.*;

/**
 * 翻译代理执行器，执行系统所有已注册的翻译处理器并执行翻译
 *
 * @author YaoWei
 * createDate 2020/11/26
 */
@Getter
@Slf4j
public class DelegateTranslateHandler implements TranslateHandler {

    private final List<TranslateHandler> translateHandlers = new ArrayList<>(16);

    @Override
    public void doTranslate(Collection<?> datas) {
        // 获取类信息，如果标注有Translate注解就翻译
        Class<?> itemClass = SailingReflectionUtils.getItemClass(datas);
        if (itemClass.getAnnotation(Translate.class) == null) {
            return;
        }
        for (TranslateHandler translateHandler : translateHandlers) {
            try {
                translateHandler.doTranslate(itemClass, datas);
            } catch (Exception ex) {
                log.error("处理器{}执行翻译失败！", translateHandler.getClass().getName(), ex);
            }
        }
    }

    @Override
    public void doTranslate(Class<?> itemClass, List<Field> translateFields, Collection<?> datas) {
        for (Field field : translateFields) {
            for (Object data : datas) {
                Object complexTypeFieldValue = SailingReflectionUtils.getField(field, data);
                this.doTranslate(complexTypeFieldValue);
            }
        }
    }

    @Override
    public SailingReflectionUtils.FieldFilter getTranslateFieldFilter() {
        return field -> !isSimpleValueType(field.getType());
    }

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }

    public void addAll(List<TranslateHandler> translateHandlers) {
        this.translateHandlers.addAll(translateHandlers);
        this.translateHandlers.sort(Comparator.comparingInt(TranslateHandler::getOrder));
    }

    /**
     * Check if the given type represents a "simple" value type: a primitive, a
     * String or other CharSequence, a Number, a Date, a URI, a URL, a Locale or a
     * Class.
     *
     * @param clazz the type to check
     * @return whether the given type represents a "simple" value type
     */
    private static boolean isSimpleValueType(Class<?> clazz) {
        return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() || CharSequence.class.isAssignableFrom(clazz)
                || Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz) || clazz.equals(URI.class)
                || clazz.equals(URL.class) || clazz.equals(Locale.class) || clazz.equals(Class.class);
    }

}

